
format ELF64 executable 3
entry main

IMG_WIDTH = 1200
IMG_HEIGHT = 800

segment readable executable

ENEIDA_UTIL_INCLUDE = 'CODE'
include 'util/util_amath.inc'
include 'util/util_image.inc'

main:
    ; alloc space for the image
    mov edi,IMG_WIDTH*IMG_HEIGHT*16
    call image_alloc
    mov [pixels_hdr],rax
    mov rbx,[pixels_hdr]
    ; loop over each pixel
    xor esi,esi
      loopy:
    xor edi,edi
      loopx:
    ; convert x coord to [-2.0; 1.0] and y coord to [-1.0; 1.0]
    cvtsi2ss xmm2,[width]
    rcpss xmm2,xmm2
    cvtsi2ss xmm3,[height]
    rcpss xmm3,xmm3
    movss xmm4,[am_v4_f32_1]
    movss xmm5,[am_v4_f32_0p5]
    cvtsi2ss xmm0,edi
    cvtsi2ss xmm1,esi
    mulss xmm0,xmm2
    subss xmm0,xmm5
    mulss xmm0,[const_3_f32]
    subss xmm0,xmm5
    mulss xmm1,xmm3
    subss xmm1,xmm5
    mulss xmm1,[const_2_f32]
    ; compute pixel color
    pxor xmm8,xmm8
    pxor xmm9,xmm9
    movss xmm10,xmm4
    pxor xmm11,xmm11
    mov ecx,100
      iterate:
    ; xmm12 = 2 * (xmm8 * xmm10 - xmm9 * xmm11) + 1.0
    movss xmm12,xmm8
    mulss xmm12,xmm10
    movss xmm13,xmm9
    mulss xmm13,xmm11
    subss xmm12,xmm13
    addss xmm12,xmm12
    addss xmm12,xmm4
    ; xmm13 = 2 * (xmm8 * xmm11 + xmm9 * xmm10)
    movss xmm13,xmm8
    mulss xmm13,xmm11
    movss xmm14,xmm9
    mulss xmm14,xmm10
    addss xmm13,xmm14
    addss xmm13,xmm13
    movss xmm10,xmm12
    movss xmm11,xmm13
    movss xmm12,xmm8
    mulss xmm12,xmm12
    movss xmm13,xmm9
    mulss xmm13,xmm13
    subss xmm12,xmm13
    ; xmm13 = 2 * xmm8 * xmm9
    movss xmm13,xmm8
    mulss xmm13,xmm9
    addss xmm13,xmm13
    addss xmm12,xmm0
    addss xmm13,xmm1
    movss xmm8,xmm12    ; xmm8 = xmm12 + xmm0
    movss xmm9,xmm13    ; xmm9 = xmm13 + xmm1
    mulss xmm12,xmm8
    mulss xmm13,xmm9
    addss xmm12,xmm13   ; xmm12 = xmm8 * xmm8 + xmm9 * xmm9
    movss xmm14,[const_100_f32]
    cmpltss xmm14,xmm12
    movd eax,xmm14
    cmp eax,-1
    je iterate_end
    sub ecx,1
    jnz iterate
      iterate_end:
    mulss xmm10,xmm10
    mulss xmm11,xmm11
    addss xmm10,xmm11
    movss xmm13,xmm12
    divss xmm13,xmm10
    sqrtss xmm13,xmm13
    mulss xmm13,xmm5
    movss xmm0,xmm12
    am_log_ss
    mulss xmm0,xmm13
    movss xmm1,[const_0p3_f32]
    am_pow_ss
    andps xmm0,xmm14
    movss xmm13,xmm0
    shufps xmm0,xmm0,00000000b
    movaps [rbx],xmm0
    add edi,1
    add rbx,16
    cmp edi,IMG_WIDTH
    jne loopx
    add esi,1
    cmp esi,IMG_HEIGHT
    jne loopy
    ; alloc space for LDR image
    mov edi,IMG_WIDTH*IMG_HEIGHT*4
    call image_alloc
    mov [pixels],rax
    ; convert to LDR
    mov rdi,[pixels]
    mov rsi,[pixels_hdr]
    mov edx,IMG_WIDTH
    mov ecx,IMG_HEIGHT
    call image_hdr2ldr
    ; save image
    mov	rdi,filename
    mov rsi,[pixels]
    mov edx,IMG_WIDTH
    mov ecx,IMG_HEIGHT
    call image_save
    ; terminate process
    mov	eax,60
    mov	edi,0
    syscall

segment readable writeable

align 4

filename db 'image_mandelbrot.tga', 0
pixels dq ?
pixels_hdr dq ?

const_0p3_f32 dd 0.3
const_2_f32 dd 2.0
const_3_f32 dd 3.0
const_100_f32 dd 100.0
width dd IMG_WIDTH
height dd IMG_HEIGHT

ENEIDA_UTIL_INCLUDE = 'DATA'
include 'util/util_amath.inc'
include 'util/util_image.inc'
